package controller

import (
	"crypto/sha1"
	"fmt"
	"github.com/kataras/iris"
	"github.com/kataras/iris/sessions"
	"github.com/mojocn/base64Captcha"
	"log"
	"math/rand"
	"net/url"
	"regexp"
	"strings"
	"time"
	"wow-web/config"
	"wow-web/dao"
	"wow-web/models"
)

type opResult struct {
	Code    int         `json:"code"`
	Data    interface{} `json:"data"`
	Message string      `json:"message"`
}
type formAccount struct {
	Mail      string `json:"mail"`
	Username  string `json:"username"`
	Password  string `json:"password"`
	Password1 string `json:"password1"`
	Code      string `json:"code"`
}

var (
	sess                   = sessions.New(sessions.Config{Cookie: "wow-cool-sec", AllowReclaim: true})
	captchaConfigCharacter = base64Captcha.ConfigCharacter{
		Height:             40,
		Width:              160,
		Mode:               base64Captcha.CaptchaModeNumberAlphabet,
		ComplexOfNoiseText: base64Captcha.CaptchaComplexLower,
		ComplexOfNoiseDot:  base64Captcha.CaptchaComplexLower,
		IsShowHollowLine:   false,
		IsShowNoiseDot:     true,
		IsShowNoiseText:    true,
		IsShowSlimeLine:    false,
		IsShowSineLine:     false,
		CaptchaLen:         5,
	}
)

type ApiController struct {
	Ctx iris.Context
}

func (c *ApiController) GetCaptcha() *opResult {
	session := sess.Start(c.Ctx)
	id, captchaInstance := base64Captcha.GenerateCaptcha("", captchaConfigCharacter)
	if c.Ctx.URLParamDefault("t", "") == "reset" {
		session.Set("CaptchaReset", id)
	} else {
		session.Set("Captcha", id)
	}
	imgBase64String := base64Captcha.CaptchaWriteToBase64Encoding(captchaInstance)
	result := opResult{}
	result.Data = imgBase64String
	return &result
}

func (c *ApiController) PostAccountCreate() *opResult {
	result := opResult{}

	var form formAccount
	c.Ctx.ReadForm(&form)
	codeId := sess.Start(c.Ctx).GetStringDefault("Captcha", "")

	if codeId == "" {
		result.Code = 1
		result.Message = "验证码异常"
	} else if !base64Captcha.VerifyCaptcha(codeId, form.Code) {
		result.Code = 2
		result.Message = "验证码错误"
	} else if matched, err := regexp.MatchString("^[a-zA-Z0-9_.-]+@[a-z0-9-]+(\\.[a-zA-Z0-9-]+)*\\.[a-zA-Z0-9]{2,6}$", form.Mail); !matched || err != nil {
		result.Code = 1
		result.Message = "邮箱错误"
	} else if matched, err := regexp.MatchString(`^(?i:[a-z][a-z\d_]{5,11})$`, form.Username); !matched || err != nil {
		result.Code = 1
		result.Message = "用户名错误"
	} else if strings.TrimSpace(form.Password) == "" {
		result.Code = 1
		result.Message = "密码格式错误"
	} else if form.Password != form.Password1 {
		result.Code = 1
		result.Message = "输入密码不一致"
	}

	if result.Code == 0 {
		form.Username = strings.ToUpper(form.Username)
		account := dao.Account.FindByUserName(form.Username)
		if account != nil {
			result.Code = 1
			result.Message = "账号已存在"
		}
		account = dao.Account.FindByRegMail(form.Mail)
		if account != nil {
			result.Code = 1
			result.Message = "邮箱已存在"
		}
		if result.Code == 0 {
			hash := sha1.New()
			hash.Write([]byte(form.Username + ":" + strings.ToUpper(form.Password)))
			sum := hash.Sum(nil)
			passSha1 := fmt.Sprintf("%X", sum)

			mail := models.Mail{
				Mail:     form.Mail,
				Username: form.Username,
				Password: passSha1,
				LastTime: time.Now(),
				Code:     fmt.Sprintf("%06d", rand.Intn(1000000)),
			}
			conf := config.GetConfig()
			mail.Url = conf.Smtp.Url + "/api/mail/verify?mail=" + url.QueryEscape(mail.Mail) + "&code=" + mail.Code

			e := dao.Mail.PreRegistration(&mail)
			if e != nil {
				result.Code = 1
				result.Message = e.Error()
			}
		}
	}
	if result.Code == 0 {
		log.Println("create account: " + form.Username)
	}
	return &result
}

func (c *ApiController) PostAccountReset() *opResult {
	result := opResult{}

	var form formAccount
	c.Ctx.ReadForm(&form)
	codeId := sess.Start(c.Ctx).GetStringDefault("CaptchaReset", "")

	if codeId == "" {
		result.Code = 1
		result.Message = "验证码异常"
	} else if !base64Captcha.VerifyCaptcha(codeId, form.Code) {
		result.Code = 2
		result.Message = "验证码错误"
	} else if matched, err := regexp.MatchString("^[a-zA-Z0-9_.-]+@[a-z0-9-]+(\\.[a-zA-Z0-9-]+)*\\.[a-zA-Z0-9]{2,6}$", form.Mail); !matched || err != nil {
		result.Code = 1
		result.Message = "邮箱错误"
	} else if matched, err := regexp.MatchString(`^(?i:[a-z][a-z\d_]{5,11})$`, form.Username); !matched || err != nil {
		result.Code = 1
		result.Message = "用户名错误"
	} else if strings.TrimSpace(form.Password) == "" {
		result.Code = 1
		result.Message = "密码格式错误"
	} else if form.Password != form.Password1 {
		result.Code = 1
		result.Message = "输入密码不一致"
	}

	if result.Code == 0 {
		form.Username = strings.ToUpper(form.Username)
		account := dao.Account.FindByUserName(form.Username)
		if account != nil {
			result.Code = 1
			result.Message = "账号已存在"
		}
		account = dao.Account.FindByRegMail(form.Mail)
		if account != nil {
			result.Code = 1
			result.Message = "邮箱已存在"
		}
		if result.Code == 0 {
			hash := sha1.New()
			hash.Write([]byte(form.Username + ":" + strings.ToUpper(form.Password)))
			sum := hash.Sum(nil)
			passSha1 := fmt.Sprintf("%X", sum)

			mail := models.Mail{
				Mail:     form.Mail,
				Username: form.Username,
				Password: passSha1,
				LastTime: time.Now(),
				Code:     fmt.Sprintf("%06d", rand.Intn(1000000)),
			}
			conf := config.GetConfig()
			mail.Url = conf.Smtp.Url + "/api/mail/verify?mail=" + url.QueryEscape(mail.Mail) + "&code=" + mail.Code

			e := dao.Mail.PreRegistration(&mail)
			if e != nil {
				result.Code = 1
				result.Message = e.Error()
			}
		}
	}
	if result.Code == 0 {
		log.Println("create account: " + form.Username)
	}
	return &result
}

func (c *ApiController) GetMailVerify() {
	mail := c.Ctx.URLParamDefault("mail", "")
	code := c.Ctx.URLParamDefault("code", "")
	if mail == "" || code == "" {
		c.Ctx.Text("error.")
		return
	}
	m := dao.Mail.GetMail(mail)
	if m == nil {
		c.Ctx.Text("已过期，重新注册")
		return
	}
	if m.Code != code {
		c.Ctx.Text("认证失败")
		return
	}
	model := dao.Account.FindByRegMail(m.Mail)
	if model != nil {
		c.Ctx.Text("邮箱已存在")
		return
	}
	a := models.Account{
		Username:    m.Username,
		ShaPassHash: m.Password,
		RegMail:     m.Mail,
		Email:       m.Mail,
	}
	e := dao.Account.CreateAccount(&a)
	if e != nil {
		c.Ctx.Text("创建账号失败: " + e.Error())
		return
	}
	dao.Mail.DeleteMail(m.Mail)
	log.Println(fmt.Sprintf("create account: %s<%s>", m.Username, m.Mail))
	c.Ctx.Redirect("/wow/success?account=" + url.QueryEscape(m.Username))
}
